package com.flute.framework.monitor;

import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.LineIterator;

public class EventParser {

	public static List<MonitedValueBlock> parseEvent(EventRequest request) {
		return parseEvent(request.getPaths(), request.getFilter());
	}

	public static List<MonitedValueBlock> parseEvent(String[] paths,
			MonitorFilter filter) {

		for (int i = 0; i < paths.length; i++) {
			paths[i] = FileHierarchy.getMachineEventsFolder(paths[i]);
		}

		Iterator<MonitedValue> valueList = getValueListInScope(paths, filter);

		// 按照eventId安装成多个块
		List<MonitedValueBlock> result = new ArrayList<MonitedValueBlock>();

		int count = 0;
		long currentId = -1;
		MonitedValueBlock block = null;
		while (valueList.hasNext()) {
			MonitedValue mv = valueList.next();
			if (count <= filter.getLatestCount()) {
				if (mv.getEventId() != currentId) {
					if (block != null) {
						result.add(block);
					}
					block = new MonitedValueBlock();
					block.addMonitedValueAtBeginning(mv);
					currentId = mv.getEventId();
					count++;
				} else {
					block.addMonitedValueAtBeginning(mv);
				}
			} else {
				break;
			}
		}

		if (result.size() < filter.getLatestCount()) {
			if (block != null) {
				result.add(block);
			}
		}

		return result;
	}

	private static Iterator<MonitedValue> getValueListInScope(String[] paths,
			MonitorFilter filter) {
		List<File> fileList = new ArrayList<File>();
		for (String path : paths) {
			File file = new File(path + filter.getKey());
			File[] files = file.listFiles();
			for (File f : files) {
				fileList.add(f);
			}
		}

		File[] files = fileList.toArray(new File[] {});
		Arrays.sort(files, new FileComparator());

		File[] neededFiles = getNeededFiles(files, filter.getDateFilter());
		System.out.println("扫描日志文件的个数：" + neededFiles.length);
		return getValueList(neededFiles, filter);
	}

	private static Iterator<MonitedValue> getValueList(final File[] files,
			final MonitorFilter filter) {
		return new Iterator<MonitedValue>() {
			Iterator<File> fileIt;
			Iterator<MonitedValue> valueIt;
			{
				List<File> list = new ArrayList<File>();
				list.addAll(Arrays.asList(files));
				fileIt = list.iterator();
			}

			@Override
			public boolean hasNext() {
				if (valueIt == null || !valueIt.hasNext()) {
					while (fileIt.hasNext()) {
						valueIt = getValues(fileIt.next(), filter).iterator();
						if (valueIt.hasNext()) {
							return true;
						}
					}
				} else {
					return valueIt.hasNext();
				}
				return false;
			}

			@Override
			public MonitedValue next() {
				return valueIt.next();
			}

			@Override
			public void remove() {
			}

		};
	}

	private static List<MonitedValue> getValues(File file, MonitorFilter filter) {
		List<MonitedValue> result = new ArrayList<MonitedValue>();
		LineIterator lineIterator = null;
		try {
			lineIterator = FileUtils.lineIterator(file, "UTF8");
			while (lineIterator.hasNext()) {
				String line = lineIterator.next();
				MonitedValue mv = MonitedValue.fromLogString(line);
				if (mv != null) {
					if ((filter.getFieldFilter() == null ? Boolean.TRUE
							: filter.getFieldFilter().meet(mv))
							&& (filter.getDateFilter() == null ? Boolean.TRUE
									: filter.getDateFilter().concludeDate(
											new StandardDate(mv.getDate())))
							&& (filter.getKey() == null ? Boolean.TRUE : filter
									.getKey().equals(mv.getKey()))
							&& (filter.getLevel() == null ? Boolean.TRUE
									: filter.getLevel() == mv.getLevel())) {
						result.add(0, mv);
					}
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			LineIterator.closeQuietly(lineIterator);
		}

		return result;
	}

	/**
	 * 根据时间戳来判断需要的文件
	 * 
	 * 因为files是从新到旧的排序，所以在区间之外的第一个文件中的内容也有可能是在时间区间之内的
	 * 
	 * 
	 * @param files
	 * @param dateFilter
	 * @return
	 */
	private static File[] getNeededFiles(File[] files, DateFilter dateFilter) {
		if (dateFilter == null) {
			return files;
		}

		List<File> neededFiles = new ArrayList<File>();

		File lastAferEnd = null;
		for (int i = 0; i < files.length; i++) {
			StandardDate fileDate = new StandardDate(files[i].lastModified());
			if ((fileDate.before(dateFilter.getEnd()) && fileDate
					.after(dateFilter.getStart()))
					|| fileDate.isSame(dateFilter.getEnd())
					|| fileDate.isSame(dateFilter.getStart())) {
				if (files[i].isFile() && files[i].getName().contains(".log")) {
					neededFiles.add(files[i]);
				}
			} else if (fileDate.after(dateFilter.getEnd())) {
				// 添加最后一次大于end的文件
				lastAferEnd = files[i];
			} else if (fileDate.before(dateFilter.getStart())) {
				// 添加第一次小于start的文件
				if (files[i].isFile() && files[i].getName().contains(".log")) {
					neededFiles.add(files[i]);
					break;
				}
			}

		}

		if (lastAferEnd != null) {
			if (lastAferEnd.isFile() && lastAferEnd.getName().contains(".log")) {
				neededFiles.add(lastAferEnd);
			}
		}

		return neededFiles.toArray(new File[] {});
	}
}

class FileComparator implements Comparator<File>, Serializable {

	private static final long serialVersionUID = -2262185466024899234L;

	@Override
	public int compare(File o1, File o2) {
		if (o1.lastModified() > o2.lastModified()) {
			return -1;
		} else if (o1.lastModified() < o2.lastModified()) {
			return 1;
		}

		return 0;
	}

}
